using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using Localization;
using SinBiota.Model.Entities.CustomAttributes;

namespace SinBiota.Model.Entities
{
    public abstract class BaseEntity
    {
        //Common persistence properties:

        [ScaffoldColumn(false)] //Does not show this property in EditorForModel and DisplayForModel html helpers.
        public virtual  int Id { get; set; }

        [LocalizedName("Version", NameResourceType = typeof(Strings))]
        [ScaffoldColumn(false)] //Does not show this property in EditorForModel and DisplayForModel html helpers.
        public virtual int Version { get; set; }
        
        // Database equality:
        private int? _oldHashCode;

        //Database Equality Implementation:
        public virtual bool Equals(BaseEntity other)
        {
            if (ReferenceEquals(null, other)) return false;
            return ReferenceEquals(this, other) || Equals(other.Id, Id);
        }
        public override int GetHashCode()
        {
            // Once we have a hash code we'll never change it
            if (_oldHashCode.HasValue)
                return _oldHashCode.Value;
            var thisIsTransient = Equals(Id, 0); //Guid.Empty);
            // When this instance is transient, we use the base GetHashCode()
            // and remember it, so an instance can NEVER change its hash code.
            if (thisIsTransient)
            {
                _oldHashCode = base.GetHashCode();
                return _oldHashCode.Value;
            }
            return Id.GetHashCode();
        }
        public override bool Equals(object obj)
        {
            var other = obj as BaseEntity;
            if (other == null)
                return false;
            // handle the case of comparing two NEW objects
            var otherIsTransient = Equals(other.Id, 0); //Guid.Empty);
            var thisIsTransient = Equals(Id, 0); //Guid.Empty);
            if (otherIsTransient && thisIsTransient)
                return ReferenceEquals(other, this);
            return other.Id.Equals(Id);
        }

        public virtual IEnumerable<string> GetAllProperties()
        {
            return GetType().GetProperties().Select(x => x.Name).Where(x => (x != "Id" & x != "Version"));
        }
    }

}
